package com.hx.learn.log.logback.mdc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Vector;

/**
 * @author jxlgcmh
 * @date 2021-08-29 17:27
 * @description
 */
public class NumberCruncherServer extends UnicastRemoteObject implements NumberCruncher {

    private static final long serialVersionUID = 1L;

    static Logger logger = LoggerFactory.getLogger(NumberCruncherServer.class);

    public NumberCruncherServer() throws RemoteException {
    }

    @Override
    public int[] factor(int number) throws RemoteException {
        // The client's host is an important source of information.
        try {
            MDC.put("client", NumberCruncherServer.getClientHost());
        } catch (java.rmi.server.ServerNotActiveException e) {
            logger.warn("Caught unexpected ServerNotActiveException.", e);
        }

        // The information contained within the request is another source
        // of distinctive information. It might reveal the users name,
        // date of request, request ID etc. In servlet type environments,
        // useful information is contained in the HttpRequest or in the
        // HttpSession.
        MDC.put("number", String.valueOf(number));

        logger.info("Beginning to factor.");

        if (number <= 0) {
            throw new IllegalArgumentException(number + " is not a positive integer.");
        } else if (number == 1) {
            return new int[]{1};
        }

        Vector<Integer> factors = new Vector<Integer>();
        int n = number;

        for (int i = 2; (i <= n) && ((i * i) <= number); i++) {
            // It is bad practice to place log requests within tight loops.
            // It is done here to show interleaved log output from
            // different requests.
            logger.debug("Trying " + i + " as a factor.");

            if ((n % i) == 0) {
                logger.info("Found factor " + i);
                factors.addElement(i);

                do {
                    n /= i;
                } while ((n % i) == 0);
            }

            // Placing artificial delays in tight loops will also lead to
            // sub-optimal results. :-)
            delay(100);
        }

        if (n != 1) {
            logger.info("Found factor " + n);
            factors.addElement(new Integer(n));
        }

        int len = factors.size();

        int[] result = new int[len];

        for (int i = 0; i < len; i++) {
            result[i] = factors.elementAt(i);
        }

        // clean up
        MDC.remove("client");
        MDC.remove("number");

        return result;
    }

    static void usage(String msg) {
        System.err.println(msg);
        System.err.println("Usage: java chapters.mdc.NumberCruncherServer configFile\n" + "   where configFile is a logback configuration file.");
        System.exit(1);
    }

    public static void delay(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
        }
    }

    public static void main(String[] args) {

        NumberCruncherServer ncs;

        try {
            ncs = new NumberCruncherServer();
            logger.info("Creating registry.");

            Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            registry.rebind("Factor", ncs);
            logger.info("NumberCruncherServer bound and ready.");
        } catch (Exception e) {
            logger.error("Could not bind NumberCruncherServer.", e);

            return;
        }
    }
}
